const net = require('net');
const HttpParser = require('./http-parser');
const Htmlparser = require('htmlparser2');
const css = require('css');

class HTTPRequest {
    constructor(options = {}) {
        this.host = options.host;
        this.method = options.method || 'GET';
        this.path = options.path || '/';
        this.port = options.port || '80';
        this.headers = options.headers;
    }
    send(body) {
        return new Promise((resolve, reject) => {
            // 构建HTTP请求
            const rows = [];
            // 模拟浏览器请求行
            rows.push(`${this.method} ${this.path} HTTP/1.1`);
            // 模拟请求头
            Object.keys(this.headers).forEach(key => {
                rows.push(`${key}: ${this.headers[key]}`)
            });
            // body
            body = Object.keys(body).map(key => (`${key}=${encodeURIComponent(body[key])}`)).join('&');
            if (body) {
                this.headers['Content-Length'] = body.length;
            };
            // GET / HTTP/1.1
            // xxx: xxx
            // 
            // 
            let data = rows.join('\r\n') + '\r\n\r\n' + body;

            // 建立TCP连接，连接成功后，传输信息
            let socket = net.createConnection({
                host: this.host,
                port: this.port
            }, () => {
                socket.write(data);
            });
            // 监听服务器返回的数据
            const parser = new HttpParser(); // 创建解析器
            socket.on('data', (chunk) => {
                // console.log(chunk.toString()); // 服务器返回的数据
                parser.parse(chunk);
                if (parse.result) {
                    resolve(parse.result);
                }
            })
        })
    }
}

function parserCss(styleText) {
    const ast = css.parse(styleText);
    // console.log(ast);
    return ast;
}

async function request() {
    const request = new HTTPRequest({
        host: '127.0.0.1',
        method: 'GET',
        port: 3000,
        path: '/',
        headers: {
            name: 'xiaotianshi',
            age: 18
        }
    });
    let { responseLine, headers, body } = await request.send({address: '北京'});
    // 对HTML进行此法分析，生成dom树，栈型结构
    let stack = { type: 'document', children: [] };
    // document html body div
    const parser = new Htmlparser.Parser({ // 内部通过状态机实现
        // 开始标签
        onopentag(name, attributes) {
            // console.log('start', name, attributes);
            let parent = stack[stack.length - 1];
            let element = {
                type: 'element',
                tagName: name,
                attributes,
                children: [],
                parent
            }
            parent.children.push(element);
            stack.push(element);
        },
        // 文本
        ontext(text) {
            // console.log('text', text);
            let parent = stack[stack.length - 1];
            let textNode = {
                type: 'text',
                text
            }
            parent.children.push(textNode);
        },
        // 闭合标签
        onclosetag(name) {
            // console.log('close', name);
            let parent = stack[stack.length - 1];
            if (name === 'style') {
                parserCss(parent.children[0].text);
            }
            stack.pop();
        }
    });
    parser.end(body); 
}

request();